package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishDto;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 菜品控制器
 */
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private CategoryService categoryService;

    @PostMapping
    // 参数怎么写，写什么？
    public R<String> save(@RequestBody DishDto dishDto){
        log.info("[新增菜品] dish:{}",dishDto);
        // 问题的是，请求的数据，并没有完全接收到?
        // 现在控制器已经拿到数据，现在需要干嘛?
        // 分开存（致据保护菜品基本信息.和菜品的口味信息)
        //  dishService 不能同时保存菜品基本信息和菜品的口味信息
        // 结论：需要自己扩展业务方法，完成保存
        dishService.saveWithFlavor(dishDto);

        // 保存后，我们需要更新redis,删除指定一个
        String key = "dish_"+dishDto.getCategoryId()+"_1";
        redisTemplate.delete(key);
        return R.success("保存成功");
    }

    // 写方法：方法名，参数列表，返回值
    /**
     * 分页获取菜品列表
     * @param page 当前页码
     * @param pageSize 每页记录数
     * @param name 按菜品名字模拟条件
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page,int pageSize,String name){
        log.info("[菜品分页]，{}，{}，{}",page,pageSize,name);
        // 分页获取，套路很固定
        // 构建Page对象
        Page pageInfo = new Page(page,pageSize);
        // 根据条件查询,按名字模糊查询，按更新日期倒叙排列
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.like(StringUtils.isNotEmpty(name),Dish::getName,name);
        dishLambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);
        // 返回page对象
        dishService.page(pageInfo,dishLambdaQueryWrapper);
        // pageInfo可以返回了
        // 现在页码展示是什么问题？不能线上分类的名称，我们也不可以直接在实体类中加入一个属性
        // 结论：返回的记录集应该用DishDto替换，因为DishDto在里面加入分类名称
        // 思路：数据已经在pageInfo的records里面了（Dish）换成DishDto
        // 构建应该Page<DishDto>
        Page<DishDto> dishDtoPage = new Page<>();
        // 复制的过程，可以忽略掉不需要的或目前没必要的属性
        // pageInfo（page,pageSize ,records,total)
        BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");
        // 我们需要单独把records里面的Dish换成DishDto
        List<Dish> records = pageInfo.getRecords();
        // 遍历这个结果集，把每条记录，换成DishDto,然后把dishDto存入应该新的列表中
        List<DishDto> dishDtoList = new ArrayList<>();
        for (Dish dish : records) {
            DishDto dishDto = new DishDto();
            // 把dish对象的数据复制dishDto
            BeanUtils.copyProperties(dish,dishDto);
            // 固定写死，先测试，后获取真实的分类名称
            // 当前菜品的分类名称，应该如何获取？
            // 结论：根据当前菜品分类的ID，通过分类业务对象，来获取分类对象。
            Category category = categoryService.getById(dish.getCategoryId());
            dishDto.setCategoryName(category.getName());
            dishDtoList.add(dishDto);
        }
        // 把新的结果集赋值给page对象
        dishDtoPage.setRecords(dishDtoList);
        return R.success(dishDtoPage);
    }

    // 方法三要素：方法名，参数，返回类型
    @GetMapping("/{id}")
    public R<DishDto> get(@PathVariable Long id){
        log.info("[根据ID，获取菜品信息]，id:{}",id);
        // 如果dishService没有对应的业务，直接返回DishDto,我们需以扩展业务方法
        DishDto dishDto = dishService.getByIdWithFlavor(id);
        return R.success(dishDto);
    }

    // 方法三要素：方法名，参数，返回类型
    @PutMapping
    public R<String> update(@RequestBody DishDto dishDto){
        log.info("[菜品修改]，dto:{}",dishDto);
        // 调用Service的业务方法，完成业务
        // dishService.updateById(dishDto); //只是更新菜品的基本信息
        dishService.updateWithFlavor(dishDto);

        // 更新菜品后，全部删除与列表有关的key,通配符
        // String keys = "dish_*";
        // redisTemplate相当于redis客户端
        // keys搜索，匹配的key,返回的列表
        Set keys = redisTemplate.keys("dish_*");
        // 如果提供的是key结合，按集合替换提供数据key删除
        redisTemplate.delete(keys);
        return R.success("更新成功");
    }

    //http://localhost:8080/dish/list?categoryId=1397844263642378242
   /* @GetMapping("/list")
    public R<List<Dish>> list(Long categoryId){
        log.info("[菜品管理-获取菜品列表],categoryId:{}",categoryId);
        List<Dish> dishList = new ArrayList<>();
        // 调用业务，获取真正的列表
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.eq(categoryId!=null,Dish::getCategoryId,categoryId);
        dishList = dishService.list(dishLambdaQueryWrapper);
        return R.success(dishList);
    }*/


   @Autowired
   private DishFlavorService dishFlavorService;

   @Autowired
  private RedisTemplate redisTemplate;

    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish){

        // 先尝试从Redis读取列表
        String key = "dish_"+dish.getCategoryId()+"_1";
        Object objectList = redisTemplate.opsForValue().get(key);
        if (objectList != null){
            List<DishDto> dishDtoList = (List<DishDto>)objectList;
            log.info("[菜品列表]，从redis读取，{}",dishDtoList);
            return R.success(dishDtoList);
        }


        //构造查询条件
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(dish.getCategoryId() != null ,Dish::getCategoryId,dish.getCategoryId());
        //添加条件，查询状态为1（起售状态）的菜品
        queryWrapper.eq(Dish::getStatus,1);
        //添加排序条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

        List<Dish> list = dishService.list(queryWrapper);

        List<DishDto> dishDtoList = list.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if(category != null){
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }

            //当前菜品的id
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
            //SQL:select * from dish_flavor where dish_id = ?
            List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
            dishDto.setFlavors(dishFlavorList);

            return dishDto;
        }).collect(Collectors.toList());

        // 存入redis
        redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);
        return R.success(dishDtoList);
    }

}
